



 class IdNumber {

    private  cityCodeObject={ // 城市代码列表  
        11: "北京", 12: "天津", 13: "河北", 14: "山西", 15: "内蒙古", 21: "辽宁", 22: "吉林",
        23: "黑龙江", 31: "上海", 32: "江苏", 33: "浙江", 34: "安徽", 35: "福建", 36: "江西",
        37: "山东", 41: "河南", 42: "湖北 ", 43: "湖南", 44: "广东", 45: "广西", 46: "海南",
        50: "重庆", 51: "四川", 52: "贵州", 53: "云南", 54: "西藏 ", 61: "陕西", 62: "甘肃",
        63: "青海", 64: "宁夏", 65: "新疆", 71: "台湾", 81: "香港", 82: "澳门", 91: "国外 "
    };

   idNumber='';
    cityCode='';

   province='';
   city='';

   district='';

   sex='';

   birthday=''

   age=0


  constructor(idNumber:string)
  {
    if(!this.isIdNumber(idNumber))
    {
      return this
    }
    this.idNumber=idNumber

    this.init(idNumber)


    return this;
  }

  public init=(id:string):void=>{
    const idv = this.fivteenConvertToEighteen(id);
    if (parseInt(idv.charAt(16)) % 2 == 0) {
        this.sex= '女'; // 女生  
    } else {
        this.sex = "男"; // 男生  
    }
    
  }

    isIdNumber=(id:string) :Boolean=>{
    let pass :Boolean=true;
    if(pass && id==='')
    {
        pass=false;
    }

     //校验长度，类型    
    if (pass && this.checkIdNumberLength(id) === false)
        pass = false;
    //检查省份    
    if (pass && this.checkProvince(id) === false)
        pass = false;
    //校验生日    
    if (pass && this.checkBirthday(id) === false)
        pass = false;
     //检验位的检测    
    if (pass && this.checkParity(id) === false)
        pass = false;
    return pass;
  }

  private  checkIdNumberLength=(id:string) :Boolean=>{
    const reg = /(^\d{15}$)|(^\d{17}(\d|X)$)/; //身份证号码为15位或者18位，15位时全为数字，18位前17位为数字，最后一位是校验位，可能为数字或字符X  
    if (reg.test(id) === false) {
        return false;
    }
    return true;
  }

  private  checkProvince=(id:string):Boolean=>{
    const province = id.substring(0, 2);
    if (this.cityCodeObject[province] == undefined) {
        return false;
    }
    this.province=this.cityCodeObject[province]
    return true;
  }

  private  checkBirthday=(id:string):Boolean=>{
    const len = id.length;
    //身份证15位时，次序为省（3位）市（3位）年（2位）月（2位）日（2位）校验位（3位），皆为数字    
    if (len === 15) {
        const re_fifteen = /^(\d{6})(\d{2})(\d{2})(\d{2})(\d{3})$/;
        const arr_data = id.match(re_fifteen) as string[]; // 正则取号码内所含出年月日数据  
        const year = arr_data[2];
        const month = arr_data[3];
        const day = arr_data[4];
        const birthday = new Date('19' + year + '/' + month + '/' + day);
        return this.checkBirthdayDate(parseInt('19' + year), month, day, birthday);
    }
    //身份证18位时，次序为省（3位）市（3位）年（4位）月（2位）日（2位）校验位（4位），校验位末尾可能为X    
    if (len === 18) {
      
        const re_eighteen = /^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$/;
        const arr_data = id.match(re_eighteen) as string[]; // 正则取号码内所含出年月日数据  
        const year = arr_data[2];
        const month = arr_data[3];
        const day = arr_data[4];
        const birthday = new Date(year + '/' + month + '/' + day);
        let b= this.checkBirthdayDate(parseInt(year), month, day, birthday);
        if(b)
        {
          this.birthday=year+'-'+month+'-'+day
          return true
        }
        return false;
    }
    return false;
  }

  private  checkBirthdayDate=(year:number, month, day, birthday):Boolean=>{
    const now = new Date();
    const now_year = now.getFullYear();
    //年月日是否合理    
    if (birthday.getFullYear() == year
        && (birthday.getMonth() + 1) == month
        && birthday.getDate() == day) {
        //判断年份的范围（3岁到150岁之间)    
        const time = now_year - year;
        this.age=time;
        if (time >= 3 && time <= 150) {
            return true;
        }
        return false;
    }
    return false;
  }

  private  checkParity=(id:string)=>{
   const card = this.fivteenConvertToEighteen(id); // 15位转18位    
   const len = card.length;
    if (len == 18) {
        const arrInt = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2);
        const arrCh = new Array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2');
        var cardTemp = 0, i;
        for (i = 0; i < 17; i++) {
          
            let idv=parseInt(id.substring(i, (i+1)));
            let rv=idv * arrInt[i]
            cardTemp =cardTemp+ rv;
        }
        let valnum = arrCh[cardTemp % 11];
        if (valnum == card.substring(17, 18)) {
            return true;
        }
        return false;
    }
    return false;
  }

  private  fivteenConvertToEighteen=(id:string):string=>{
    if (id.length == 15) {
        const arrInt = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2);
        const arrCh = new Array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2');
        var cardTemp = 0, i;
        id = id.substring(0, 6) + '19' + id.substring(6, id.length - 6);
        for (i = 0; i < 17; i++) {
            cardTemp += parseInt(id.substring(i, (i+1))) * arrInt[i];
        }
        id += arrCh[cardTemp % 11];
        return id;
    }
    return id;
  }


}









export default IdNumber  //导出